use crate::config::DB;
use crate::dto::sys_dept::DeptResp;
use crate::dto::sys_user::{UserLoginReq, UserResp, UserWithDept};
use crate::entity::table::{SysDept, SysUser};
use crate::middleware::jwt::AuthBody;
use crate::util::copy;
use crate::util::rand_utils::encrypt_password;
use crate::util::web_utils::get_client_info;
use hypers::prelude::Request;
use hypers::prelude::{Error, Result};
use rbs::to_value;
use crate::middleware::jwt::JWTClaims;

/// 用户登录
pub async fn login(login_req: UserLoginReq, req: &Request) -> Result<AuthBody> {
    let mut msg = "登录成功".to_string();
    let mut status = "1".to_string();
    // 验证验证码
    if encrypt_password(&login_req.code, "") != login_req.uuid {
        msg = "验证码错误".to_owned();
        status = "0".to_owned();
        set_login_info(
            req,
            "".to_owned(),
            login_req.user_name.clone(),
            msg.clone(),
            status,
            None,
            None,
        )
        .await;
        return Err(Error::Other(msg));
    }
    // 根据用户名获取用户信息
    let user = DB
        .query_decode::<SysUser>(
            "SELECT * from sys_user WHERE user_name = ?",
            vec![to_value!(&login_req.user_name)],
        )
        .await
        .unwrap();
    if user.id == "0" {
        msg = "用户不存在".to_owned();
        status = "0".to_owned();
        set_login_info(
            req,
            "".to_owned(),
            login_req.user_name,
            msg.clone(),
            status,
            None,
            None,
        )
        .await;
        return Err(Error::Other(msg));
    } else if user.user_status == "0" {
        msg = "用户已被禁用".to_owned();
        status = "0".to_owned();
        set_login_info(
            req,
            "".to_owned(),
            login_req.user_name,
            msg.clone(),
            status,
            None,
            None,
        )
        .await;
        return Err(Error::Other(msg));
    }
    //  验证密码是否正确
    if encrypt_password(&login_req.user_password, &user.user_salt) != user.user_password {
        msg = "密码错误".to_owned();
        status = "0".to_owned();
        set_login_info(req, "".to_owned(), login_req.user_name, msg.clone(), status, None, None).await;
        return Err(Error::Other(msg));
    }
    // 注册JWT
    let token_id = scru128::new_string();
    let claims = JWTClaims::new(user.id.clone(), token_id.clone(), login_req.user_name.clone());
    let token = claims.generate_token()?;
    // 成功登录后
    //  写入登录日志
    set_login_info(req, user.id.clone(), login_req.user_name, msg, status, Some(token_id), Some(token.clone())).await;
    Ok(token)
}

pub async fn set_login_info(
    req: &Request,
    u_id: String,
    login_name: String,
    msg: String,
    status: String,
    token_id: Option<String>,
    token: Option<AuthBody>,
) {
    let header = req.headers().to_owned();
    let remote_addr = req.remote_addr().to_owned();
    let u = get_client_info(header, remote_addr).await;

    // 写入登录日志
    // 如果成功，写入在线日志
    if status == "1" {
        if let (Some(token_id), Some(token)) = (token_id, token) {
            super::sys_user_online::add(u.clone(), u_id, token_id, token.exp).await;
        }
    };
    super::sys_login_log::add(u, login_name, msg, status).await;
}

pub async fn get_by_id(user_id: &str) -> rbatis::Result<UserWithDept> {
    let user = DB
        .query_decode::<SysUser>(
            "select * from sys_user WHERE deleted_at IS NULL and id = ?",
            vec![to_value!(user_id)],
        )
        .await?;
    let depts = DB
        .query_decode::<SysDept>(
            "SELECT * from sys_dept WHERE dept_id = ? ",
            vec![to_value!(&user.dept_id)],
        )
        .await?;
    let res = UserWithDept {
        user: copy::<UserResp>(&user),
        dept: copy::<DeptResp>(&depts),
    };
    Ok(res)
}
